package com.tlvip.design.factory.v2;

/**
 * <p>description：</p>
 * 抽象工厂模式定义：
 * 提供一个创建一系列相关或互相依赖对象的接口，而无需指定他们具体的类
 *
 * 应用场景
 *  程序需要处理不同系列的相关产品，但是您不希望它依赖于这些产品的具体类时，可以使用抽象工厂。
 *
 *  优点：
 *      可以确信你从工厂得到的产品彼此是兼容的。
 *      可以避免具体产品和客户端代码之间的紧密耦合
 *      符合单一职责原则
 *      符合开闭原则
 *
 *  JDK
 *      Connection相关接口，java提供接口规范，具体由不同厂商自己实现，相互不影响。
 * 三者区别
 *  TestFactory 用Application调用工厂，并通过传type来实例化不同产品，当增加产品时，需要修改SimpleFactory。
 *
 *  TestFactoryV1 抽象Application，
 *     将变化的部分createProduct()延迟到子类中实现
 *     将固定部分getObject()保留在父类中。
 *     通过实例化不同的Application来获取对应的产品实例
 *     避免对Application的修改，降低编码风险。
 *
 *  TestAbstractFactory
 *     顶层接口定义规范，IConnection，ICommand，并定义IDatabaseUtils来组合抽象接口
 *     具体实现交由不同客户端，
 *     最终调用仍然按照约定方式来
 *     不依赖于具体实现，解耦客户端
 * <p>copyright： copyright(C)2016-2099</p>
 * <p>Life is short,we need passion</p>
 * <p>Summary： </p>
 * <p>instructions： </p>
 * Date 2021/8/15</p>
 * Author mac
 *
 * @version 1.0
 */
public class TestAbstractFactory {
    public static void main(String[] args) {
        IDatabaseUtils iDatabaseUtils = new MysqlDataBaseUtils();
        IConnection connection = iDatabaseUtils.getConnection();
        connection.connect();
        ICommand command = iDatabaseUtils.getCommand();
        command.command();

        System.out.println("-------------------");

        IDatabaseUtils oracleDataBaseUtils = new OracleDataBaseUtils();
        IConnection oracleConnection = oracleDataBaseUtils.getConnection();
        oracleConnection.connect();
        ICommand oracleCommand = oracleDataBaseUtils.getCommand();
        oracleCommand.command();
    }
}

// 先定义规范
interface IConnection {
    void connect();
}

class MysqlConnection implements IConnection {

    @Override
    public void connect() {
        System.out.println("mysql connected.");
    }
}

class OracleConnection implements IConnection {

    @Override
    public void connect() {
        System.out.println("oracle connect.");
    }
}

// 先定义规范
interface ICommand {
    void command();
}

class MysqlCommand implements ICommand {

    @Override
    public void command() {
        System.out.println("mysql command.");
    }
}

class OracleCommand implements ICommand {

    @Override
    public void command() {
        System.out.println("oracle command.");
    }
}

// 先定义规范-将一系列相关依赖的接口定义组合到一块
interface IDatabaseUtils {
    IConnection getConnection();

    ICommand getCommand();
}

class MysqlDataBaseUtils implements IDatabaseUtils {

    @Override
    public IConnection getConnection() {
        return new MysqlConnection();
    }

    @Override
    public ICommand getCommand() {
        return new MysqlCommand();
    }
}

class OracleDataBaseUtils implements IDatabaseUtils {

    @Override
    public IConnection getConnection() {
        return new OracleConnection();
    }

    @Override
    public ICommand getCommand() {
        return new OracleCommand();
    }
}